﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using 旅游管理系统.Database;
using 旅游管理系统.Models;

namespace 旅游管理系统.Services
{
    //接口的实现
    public class TouristRouteRepository : ITouristRouteRepository
    {
        private readonly AppDbContext _context; //上下文关系
        public TouristRouteRepository(AppDbContext appDbContext)
        {
            _context = appDbContext;
        }

        public async Task<TouristRoute> GetTouristRouteAsync(Guid touristRouteId)
        {
            return await _context.TouristRoutes.Include(t => t.TouristRoutePictures).FirstOrDefaultAsync(n => n.Id == touristRouteId);
        }

        public async Task<IEnumerable<TouristRoute>> GetTouristRoutesAsync(string keyword,
            string ratingOperator, 
            int? ratingValue
        )
        {
            IQueryable<TouristRoute> result = _context //使用IQueryable，产生一个查询TouristRoutes表，并连接TouristRoutePictures表的 SQL语句
                .TouristRoutes      //IQueryable 可以用来进行数据库的延迟操作，
                .Include(t => t.TouristRoutePictures); //生成了 SQL语句，并没有执行数据库查询的操作
            if(!string.IsNullOrWhiteSpace(keyword)) //意思是 keyword != null || keyword != ""
            {
                keyword = keyword.Trim();
                result = result.Where(t => t.Title.Contains(keyword));
            }
            //上面已经使用过 IQueryable了，只需要对传入的参数做一个判断，如果 ratingValue >=0 才需要过滤，否则不需要做任何动作
            if(ratingValue >= 0)
            {
                result = ratingOperator switch
                {
                    "largerThan" => result.Where(t => t.Rating >= ratingValue),
                    "lessThan" => result.Where(t => t.Rating <= ratingValue),
                    _ => result.Where(t => t.Rating == ratingValue),
                }; //switch 语句的自动变种.  是C#中新的用函数式写法写的 switch语句
            }

            //IQueryable是 Linq to SQL的返回类型，简单来说，IQueryable可以叠加处理 Linq语句，最后统一返回数据库，而这个处理过程就叫做延迟执行
            // Include Vs join ,Include是使用外键进行连接，而 join是不通过外键，是通过手动的将两张表链接，通过使用这两个函数可以实现数据的立即加载 Eager Load,
            //entity framework还提供了另外一种加载方式  延时加载 Lazy Load，不使用 Include函数和 join函数进行连接
            return await result.ToListAsync(); //Include 就是 entity framework中链接两张表的方法，Include是通过外键来进行链接
        }

        public async Task<bool> TouristRouteExistsAsync(Guid touristRouteId)
        {
            //使用 _context来调用数据库
            //使用 Any()来判断数据是否存在 ,存在返回 true,否则返回 false
            return await _context.TouristRoutes.AnyAsync(t => t.Id == touristRouteId);
        }

        public async Task<IEnumerable<TouristRoutePicture>> GetPicturesByTouristRouteIdAsync(Guid touristRouteId)
        {
            return await _context.TouristRoutePictures
                .Where(p => p.TouristRouteId == touristRouteId).ToListAsync();
        }

        public async Task<TouristRoutePicture> GetPictureAsync(int pictureId)
        {
            return await _context.TouristRoutePictures
                .Where(p => p.Id == pictureId).FirstOrDefaultAsync();
        }
        public async Task<IEnumerable<TouristRoute>> GetTouristRoutesByIDListAsync(IEnumerable<Guid> ids)
        {
            return await _context.TouristRoutes.Where(t => ids.Contains(t.Id)).ToListAsync(); // 获取数据空中某一数据
        }
        public void AddTouristRoute(TouristRoute touristRoute)
        {
            if(touristRoute == null)
            {
                throw new ArgumentNullException(nameof(touristRoute)); //抛出个新的空数据异常
            }
            _context.TouristRoutes.Add(touristRoute); //新数据可以保存在上下文关系对象中了，但还没有把数据写入数据库中
            //把数据写入数据库中
            //_context.SaveChanges();
        }

        public void AddTouristRoutePicture(Guid touristRouteId,TouristRoutePicture touristRoutePicture)
        {
            if(touristRouteId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(touristRouteId)); //抛  名为touristRouteId 的异常
            }
            if(touristRoutePicture == null)
            {
                throw new ArgumentNullException(nameof(touristRoutePicture));
            }
            touristRoutePicture.TouristRouteId = touristRouteId;
            _context.TouristRoutePictures.Add(touristRoutePicture); //添加进入上下文关系对象
        }

        public void DeleteTouristRoute(TouristRoute touristRoute)
        {
            _context.TouristRoutes.Remove(touristRoute);
        }
        public void DeleteTouristRotuePicture(TouristRoutePicture picture)
        {
            _context.TouristRoutePictures.Remove(picture);
        }
        public void DeleteTouristRoutes(IEnumerable<TouristRoute> touristRoutes)
        {
            _context.TouristRoutes.RemoveRange(touristRoutes); //使用RemoveRange来批量删除数据
        }
        public async Task<bool> SaveAsync()
        {
            return (await _context.SaveChangesAsync() >= 0); //大于0 则保存成功，小于0则保存失败
        }
    }
}
